package nbcp.myoql.listener

import nbcp.base.comm.config
import nbcp.base.event.RedisMachineIdEvent
import nbcp.base.event.RequestInitEvent
import nbcp.base.extend.AsBoolean
import nbcp.base.extend.AsInt
import nbcp.base.extend.Important
import nbcp.base.utils.MyUtil
import nbcp.base.utils.SpringUtil
import nbcp.myoql.db.flyway.FlywayMongoBeanProcessor
import nbcp.myoql.db.db
import org.slf4j.LoggerFactory
import org.springframework.boot.context.event.ApplicationStartedEvent
import org.springframework.context.annotation.Configuration
import org.springframework.context.annotation.Import
import org.springframework.context.event.EventListener

@Import(FlywayMongoBeanProcessor::class)
@Configuration
class MyOqlApplicationStartedListener {
    companion object {
        private val logger = LoggerFactory.getLogger(this::class.java.declaringClass)
    }

    @EventListener
    fun requestInit(ev: RequestInitEvent) {
        db.currentRequestChangeDbTable.clear()
    }

    @EventListener
    fun redisMachineId(ev: RedisMachineIdEvent) {

        var appName = ev.appName;
        var localUsedIpPort = ev.localUsedIpPort;
        //第一次初始化应用。
        val redisInstances = db.rerBase.nacosInstance(appName).getMap()
            .mapValues { it.value.AsInt() }
            .toMutableMap()


        if (redisInstances.isEmpty() || !redisInstances.containsKey(localUsedIpPort)) {
            redisInstances.put(localUsedIpPort, 0);
        }

        fillMachineId(redisInstances);
        var machineId = redisInstances.get(localUsedIpPort).AsInt();

        db.rerBase.nacosInstance(appName).resetMap(redisInstances);

        ev.result = machineId;
    }


    /**
     * 填充Id
     */
    private fun fillMachineId(redisNacosInstanceNewData: MutableMap<String, Int>) {
        var usedIds = redisNacosInstanceNewData.values.toSet();

        redisNacosInstanceNewData
            .filter { it.value == 0 }
            .keys
            .forEach { ipPort ->
                var randomId = 0;
                (1..6).forEach for1@{
                    randomId = MyUtil.getRandomNumber(100, 500);
                    if (usedIds.contains(randomId) == false) {
                        return@for1
                    }
                }

                redisNacosInstanceNewData.put(ipPort, randomId);
            }
    }

    @EventListener
    fun dbInitOnApplicationStarted(ev: ApplicationStartedEvent) {

        if (config.getConfig("app.flyway.enable", "true").AsBoolean(true)) {
            val flyways = SpringUtil.getBeanWithNull(FlywayMongoBeanProcessor::class.java)
            if (flyways != null) {
                flyways.playFlyVersion();
            }
        }

        db.mongo.groups.map { it::class.java.simpleName }.apply {
            if (this.any()) {
                logger.Important("mongo groups: " + this.joinToString(","))
            }
        }

        db.sql.groups.map { it::class.java.simpleName }.apply {
            if (this.any()) {
                logger.Important("sql groups: " + this.joinToString(","))
            }
        }
    }
}